package com.miaoxun.common.encrypt;

import org.apache.commons.codec.digest.DigestUtils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.UUID;

public class Encrypt {
    /**
     * login
     */
    public static class LoginPwd {
        private static String DES3KEY = "t#IrXo(9^GA-Mq(g3Y[pWS!9";

        public static String Encode(String pwd) {
            try {
                //先3Des加密
                String desStr = DES3.encode3Des(pwd, DES3KEY);
                System.out.println(desStr);
                String md5Str = Encrypt.ABC.MD5(desStr).toLowerCase();
                System.out.println(md5Str);
                return md5Str;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }


    /**
     * md5 /sha256
     */

    public static class ABC {
        /**
         * MD5函数
         *
         * @param str
         * @return
         */
        public static String MD5(String str) {

            return DigestUtils.md5Hex(str);
        }

        /**
         * SHA256函数
         *
         * @param str
         * @return
         */
        public static String SHA256(String str) {
            return DigestUtils.sha256Hex(str);  //返回长度为44字节的字符串
        }
    }

    /**
     * key
     */
    public static class CreatKey {
        /**
         * 随机字符串 32 中间有-
         */
        public static String GetGUID() {
            return UUID.randomUUID().toString();
        }
    }


    /**
     * base64
     */
    public static class Base64 {
        /**
         * base64
         *
         * @param source
         * @return
         */
        public static String EncodeBase64(String source) {

            return new org.apache.commons.codec.binary.Base64().encodeToString(source.getBytes());
        }

        public  static   byte[] decode(String str){
            return  new org.apache.commons.codec.binary.Base64().encode(str.getBytes());
        }
        public  static  String      encodeBase64String(byte[] bytes){
            return  new org.apache.commons.codec.binary.Base64().encodeBase64String(bytes);
        }
        /**
         * @param result
         * @return
         */
        public static String DecodeBase64(String result) {
            return new String(new org.apache.commons.codec.binary.Base64().decode(result.getBytes()));
        }
    }


    public static class DES3 {
        /**
         * 3DES加密
         * @param key 密钥，24位
         * @param srcStr 将加密的字符串
         * @return
         *
         * lee on 2017-08-09 10:51:44
         */
        public static String  encode3Des(String srcStr,String key){
            byte[] keybyte = key.getBytes();
            byte[] src = srcStr.getBytes();
            try {
                //生成密钥
                SecretKey deskey = new SecretKeySpec(keybyte, "DESede");
                //加密
                Cipher c1 = Cipher.getInstance("DESede");
                c1.init(Cipher.ENCRYPT_MODE, deskey);

                String pwd = Base64.encodeBase64String(c1.doFinal(src));
                return pwd;
            } catch (java.security.NoSuchAlgorithmException e1) {

                e1.printStackTrace();
            }catch(javax.crypto.NoSuchPaddingException e2){
                e2.printStackTrace();
            }catch(java.lang.Exception e3){
                e3.printStackTrace();
            }
            return null;
        }

        /**
         * 3DES解密
         * @param key 加密密钥，长度为24字节
         * @param desStr 解密后的字符串
         * @return
         *
         * lee on 2017-08-09 10:52:54
         */
        public static String decode3Des( String desStr,String key){

            byte[] keybyte = key.getBytes();
            byte[] src = Base64.decode(desStr);
            try {

                SecretKey deskey = new SecretKeySpec(keybyte, "DESede");
                Cipher c1 = Cipher.getInstance("DESede");
                c1.init(Cipher.DECRYPT_MODE, deskey);
                String pwd = new String(c1.doFinal(src));
                return pwd;
            } catch (java.security.NoSuchAlgorithmException e1) {
                e1.printStackTrace();
            }catch(javax.crypto.NoSuchPaddingException e2){
                e2.printStackTrace();
            }catch(java.lang.Exception e3){
                e3.printStackTrace();
            }
            return null;
        }
    }


    public static class DES {
        private final static String DES = "DES";
        private static final String UTF_8 = "UTF-8";

        /**
         * Description 根据键值进行加密
         *
         * @param data
         * @param key  加密键byte数组
         * @return
         * @throws Exception
         */
        public static String encrypt(String data, String key) throws Exception {
            byte[] bt = encrypt(data.getBytes(UTF_8), key.getBytes(UTF_8));
            String strs = org.apache.commons.codec.binary.Base64.encodeBase64String(bt);
            return strs;
        }

        /**
         * Description 根据键值进行解密
         *
         * @param data
         * @param key  加密键byte数组
         * @return
         * @throws java.io.IOException
         * @throws Exception
         */
        public static String decrypt(String data, String key) throws Exception {
            if (data == null)
                return null;
            byte[] buf = org.apache.commons.codec.binary.Base64.decodeBase64(data);
            byte[] bt = decrypt(buf, key.getBytes(UTF_8));
            return new String(bt, UTF_8);
        }

        /**
         * Description 根据键值进行加密
         *
         * @param data
         * @param key  加密键byte数组
         * @return
         * @throws Exception
         */
        private static byte[] encrypt(byte[] data, byte[] key) throws Exception {
            // 生成一个可信任的随机数源
            SecureRandom sr = new SecureRandom();

            // 从原始密钥数据创建DESKeySpec对象
            DESKeySpec dks = new DESKeySpec(key);

            // 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey securekey = keyFactory.generateSecret(dks);

            // Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance(DES);

            // 用密钥初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);

            return cipher.doFinal(data);
        }

        /**
         * Description 根据键值进行解密
         *
         * @param data
         * @param key  加密键byte数组
         * @return
         * @throws Exception
         */
        private static byte[] decrypt(byte[] data, byte[] key) throws Exception {
            // 生成一个可信任的随机数源
            SecureRandom sr = new SecureRandom();

            // 从原始密钥数据创建DESKeySpec对象
            DESKeySpec dks = new DESKeySpec(key);

            // 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey securekey = keyFactory.generateSecret(dks);

            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance(DES);

            // 用密钥初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, sr);

            return cipher.doFinal(data);
        }
    }


    public static class FileHashUtil {
        public static final char[] hexChar = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        public static final String[] hashTypes = new String[] { "MD2", "MD5", "SHA1", "SHA-256", "SHA-384", "SHA-512" };

        public void MD5File(String fileName) throws Exception{
            //String fileName = args[0];
            System.out.println("需要获取hash的文件为：　" + fileName);
            java.util.List<MessageDigest> mds = new java.util.ArrayList<MessageDigest>();
            for (String hashType : hashTypes) {
                MessageDigest md = MessageDigest.getInstance(hashType);
                mds.add(md);
            }
            InputStream fis = null;
            try {
                fis = new FileInputStream(fileName);
                byte[] buffer = new byte[1024];
                int numRead = 0;
                while ((numRead = fis.read(buffer)) > 0) {
                    for (MessageDigest md : mds) {
                        md.update(buffer, 0, numRead);
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                if (fis != null) {
                    fis.close();
                }
            }

        }

    }
}
